//#ifdef HAVE_CONFIG_H
//#  include <config.h>
//#endif

#include <config.h>
#include <gtk/gtk.h>
#include "callbacks.h"
#include "interface.h"
#include "support.h"
#include "monster.h"
#include  <pthread.h>
#include <sys/time.h>

#ifdef timersub//重新定义timersub
#undef timersub
#endif
#define timersub(a, b, result)					\
	do {							\
	(result).tv_sec = (a).tv_sec - (b).tv_sec;		\
	(result).tv_usec = (a).tv_usec - (b).tv_usec;		\
	if ((result).tv_usec < 0) {				\
	--(result).tv_sec;					\
	(result).tv_usec += 1000000;				\
	}							\
	} while (0)


/* 下面是IP地址格式 */
typedef u_int32_t in_addr_t;
int packet_length = 0;

const u_char *packet_content;
u_short ethernet_type;
u_char *mac_string;
gchar* Info[5] = {"长度","源IP","源MAC","目的IP","目的MAC"};
gchar* IPInfo[6] = {"源IP", "源端口(ICMP操作类型)", "目的IP", "目的端口", "上层协议", "总长"};

/*gchar* IPInfo[6] = {"11111111111111111", "22222222222222222222", "3333333333333333333", "44444444444444444444", "5555555555555555555555", "6666666666666666666"};*/

extern int flag1;
extern int flag2;
extern int count1;
extern int count2;

extern long packet_total_len;
extern GtkWidget *datas_entry;
extern GtkWidget *packets_num_entry;
extern GtkWidget *current_speed_entry;
extern long packet_num;
extern long current_speed;
extern GtkWidget *clist1;
extern GtkWidget *clist2;

pcap_t *pcap_handle;
/* Libpcap句柄 */
char error_content[PCAP_ERRBUF_SIZE];
char *net_interface; /* 网路接口 */
char bpf_filter_string[8]="arp";
/* 过滤规则字符串，此时表示本程序只是捕获IP协议的数据包，同样也是以太网数据包。 */
bpf_u_int32 net_mask;
/* 网络掩码 */
bpf_u_int32 net_ip;
/* 网络地址 */
char *net_interface;
/* 网络接口 */
struct pcap_pkthdr protocol_header;
/* 数据包信息 */
struct ether_header *ethernet_protocol;
/* 以太网协议变量 */


gboolean on_QUIT_destroy_event(GtkWidget *widget,
                               GdkEvent *event,
                               gpointer user_data)
{
   gtk_main_quit();
   return FALSE;
}

void on_chose2_pressed(GtkButton *button)
{
   count1++;
   if (count1 %2 != 0)
   {
      flag1 = 1;//选择正常模式，则设为0
      memcpy(bpf_filter_string,"ip",sizeof("ip"));
      fprintf(stderr, "flag1 = 1 IP\n");
   }
   else
      flag1 = 0;
}

void on_chose1_pressed(GtkButton *button)
{
   count2++;
   if (count2 %2 != 0)
   {
      flag2 = 1; //混杂模式，则设为1
      memcpy(bpf_filter_string,"arp",sizeof("arp"));
      fprintf(stderr, "flag2 = 1 ARP\n");
   }
   else
      flag2 = 0;
}

void on_START_pressed(GtkButton *button)
{
    struct sockaddr_in in_addr;
    struct ethhdr  *eth_hdr;
    struct ip *ip;
    int sock,recv_len, addr_len;

    struct bpf_program bpf_filter;//放到全局的时候 会出错

    net_interface = pcap_lookupdev(error_content);
    /* 获得网络接口 */
    pcap_lookupnet(net_interface,  /* 网络接口 */ 
                   &net_ip,  /* 网络地址 */ 
                   &net_mask,  /* 网络掩码 */
                   error_content); /* 错误信息*/
    /* 获得网络地址和网络掩码 */
    pcap_handle = pcap_open_live(net_interface,  /* 网络接口 */
                                 BUFSIZ,  /* 数据包大小 */
                                 1,  /* 混杂模式 */
                                 0,  /* 等待时间 */
                                 error_content); /* 错误信息 */
    /* 打开网络接口 */
    pcap_compile(pcap_handle,  /* Libpcap句柄 */
                 &bpf_filter,  /* BPF过滤规则 */
                 bpf_filter_string,  /* 过滤规则字符串 */
                 0,  /* 优化参数 */
                 net_ip); /* 网络地址 */
    pcap_setfilter(pcap_handle,  /* Libpcap句柄 */ 
                   &bpf_filter); /* BPF过滤规则 */
    /* 设置规律规则 */

    if (pcap_datalink(pcap_handle) != DLT_EN10MB)
        return ;

    pthread_t MyCaptureThread;/* 创建线程进行数据包捕获 */
    pthread_create (&MyCaptureThread, NULL,(void *)caputure,0);

//////////////////////////////////////////////////////////////////////
   if(flag2 == 1)//ARP
   {
       GtkWidget *ARP_PACKETS;
       ARP_PACKETS = create_ARP_PACKETS();
       gtk_widget_show (ARP_PACKETS);
       fprintf(stderr, "ARP Packets showed, now to enter lookup widget",
               sizeof("ARP Packets showed, now to enter lookup widget"));
       datas_entry = lookup_widget(ARP_PACKETS, "RECIEVED_DATAS");
       current_speed_entry =  lookup_widget(ARP_PACKETS, "CURRENT_SPEED");
       packets_num_entry = lookup_widget(ARP_PACKETS, "PACKETS_NUM");
   }
   if(flag1 == 1)//IP
   {
       GtkWidget *IP_PACKETS;
       IP_PACKETS = create_IP_PACKETS();
       gtk_widget_show (IP_PACKETS);

       fprintf(stderr,"IP Packets showed, now to enter lookup widget",
                      sizeof("IP Packets showed, now to enter lookup widget"));

       datas_entry = lookup_widget(IP_PACKETS, "RECIEVED_DATAS");
       current_speed_entry =  lookup_widget(IP_PACKETS, "CURRENT_SPEED");
       packets_num_entry = lookup_widget(IP_PACKETS, "PACKETS_NUM");
   }

   time_control();/* 进入时间循环 */
   gtk_main();/* 让界面不退出 等待消息 */

   pthread_exit(&MyCaptureThread);/* 抓包线程结束 */

}
/////////////////////////////////显示总的数据量///////////////////////////////////////
void on_RECIEVED_DATAS_activate(GtkEntry *entry, long packet_total_len)
{
   gchar *DATA_NUM = NULL;
   float num_f;
   if(packet_total_len <= 1024)
   {
      DATA_NUM = g_strdup_printf("%ld b",packet_total_len);
   }
   else
   {
      num_f = ((float)packet_total_len)/1024;
      if(num_f >=1024)
      {
         num_f = num_f/1024;
         DATA_NUM = g_strdup_printf("%0.2f Mb",num_f);
      }
      else 
         DATA_NUM = g_strdup_printf("%0.2f kb",num_f);
   }
   gtk_entry_set_text(entry,DATA_NUM);
}

void * caputure (void)
{
    struct sockaddr_in in_addr;
    struct ethhdr  *eth_hdr;
    struct ip *ip;
    struct timeval	tv0;	/* start */
    struct timeval	tv1;	/* end */
    struct timeval	tv_delta;/* difference tv1 - tv0 */

    float recvtime = 0.0;

    while(1)
    {
       gettimeofday(&tv0, NULL);//获取当前时间
       if (flag1)
	  IP_callback();
       if (flag2)
          ARP_callback();
       gettimeofday(&tv1, NULL);//获取当前时间
       timersub(tv1, tv0, tv_delta);//计算抓包用的时间
       recvtime =  tv_delta.tv_sec + tv_delta.tv_usec/1000;
       if(recvtime != 0)
           current_speed = 100/recvtime;
       else
           current_speed = 100;
   }
}

void on_CURRENT_SPEED_activate(GtkEntry *entry, long speed)
{
    gchar *CURRENT_SPEED=NULL;
    if(speed <1024)
       CURRENT_SPEED=g_strdup_printf("%ld B/s",speed);
    else if(speed < 1024*1024)
    {
       speed = speed / 1024;
       CURRENT_SPEED=g_strdup_printf("%ld KB/s",speed);
    }
    else if(speed<1024*1024*1024)
    {
       speed = speed / (1024*1024);
       CURRENT_SPEED=g_strdup_printf("%ld MB/s",speed);
    }
    gtk_entry_set_text(entry,CURRENT_SPEED);
}

void on_PACKETS_NUM_activate(GtkEntry *entry, long packet_num)
{
    gchar *PACKET_NUM = NULL;
    PACKET_NUM=g_strdup_printf("%ld",packet_num);
    gtk_entry_set_text(entry,PACKET_NUM);
}


void ARP_callback(void)
{
    int i,j;
    struct arp_header
    {
       u_int16_t arp_hardware_type;
       /* 硬件地址类型 */
       u_int16_t arp_protocol_type;
       /* 协议地址类型 */
       u_int8_t arp_hardware_length;
       /* 硬件地址长度 */
       u_int8_t arp_protocol_length;
       /* 协议地址长度 */
       u_int16_t arp_operation_code;
       /* 操作类型 */
       u_int8_t arp_source_ethernet_address[6];
       /* 源以太网地址 */
       u_int8_t arp_source_ip_address[4];
       /* 源IP地址 */
       u_int8_t arp_destination_ethernet_address[6];
       /* 目的以太网地址 */
       u_int8_t arp_destination_ip_address[4];
       /* 目的IP地址 */
    };

      packet_content=pcap_next(pcap_handle,&protocol_header);
      packet_num++;
      fprintf(stderr,"--------------------*****-----------------------\n");
      fprintf(stderr,"Capture a Packet from net_interface :\n");
      fprintf(stderr,"%s \n", net_interface);
      /* 输出网络接口 */
      fprintf(stderr,"Capture Time is:\n");
      fprintf(stderr, "%s", ctime((const time_t*) &protocol_header.ts.tv_sec));
      /* 输出此数据包的时间信息 */

      fprintf(stderr,"Packet Length is:\n");
      packet_length = protocol_header.len;
      packet_total_len = packet_total_len + packet_length;
      fprintf(stderr,"%d\n", protocol_header.len);
      /* 输出此数据包的长度信心 */

      ethernet_protocol = (struct ether_header*)packet_content;

      fprintf(stderr,"Ethernet type is :\n");
      ethernet_type = ntohs(ethernet_protocol->ether_type);
      /* 获得以太网的类型，它表示上层协议的类型，即网路层的协议类型。 */
      fprintf(stderr,"%04x\n", ethernet_type);
      /* 输出以太网类型 */

    switch (ethernet_type)
    {
        case 0x0800:
            fprintf(stderr,"The network layer is IP protocol\n");
            //Info[2] = g_strdup_printf("%s", "IP");
            break;
            /* 如果以太网类型是0x0800就表示上层协议类型为IP协议 */
        case 0x0806:
            fprintf(stderr,"The network layer is ARP protocol\n");
            //Info[2] = g_strdup_printf("%s", "ARP");
         break;
            /* 如果以太网类型是0x0806就表示上层协议类型为ARP协议 */
        case 0x8035:
            fprintf(stderr,"The network layer is RARP protocol\n");
            //Info[2] = g_strdup_printf("%s", "RARP");
            break;
            /* 如果以太网类型是0x8035就表示上层协议类型为RARP协议 */
        default:
            break; /* 其他以太网类型，在这里没有分析 */
    }
    fprintf(stderr,"Mac Source Address is : \n");
    mac_string = ethernet_protocol->ether_shost;
    /* 获得源以太网地址 */
    fprintf(stderr,"%02x:%02x:%02x:%02x:%02x:%02x\n",  *mac_string, *(mac_string + 1), *(mac_string + 2), *(mac_string + 3), *(mac_string + 4), *(mac_string + 5));
    Info[2] = g_strdup_printf("%02x:%02x:%02x:%02x:%02x:%02x",  *mac_string, *(mac_string + 1), *(mac_string + 2), *(mac_string + 3), *(mac_string + 4), *(mac_string + 5));
    /*
     * 要对以太网地址进行转换，使它变成字符串形式进行显示，例如11:11:11:11:11:11。因为读到的源以太网地址是字节流顺序的
     */
    fprintf(stderr,"Mac Destination Address is : \n");
    mac_string = ethernet_protocol->ether_dhost;
    /* 获得目的以太网地址 */
    fprintf(stderr,"%02x:%02x:%02x:%02x:%02x:%02x\n",  *mac_string, *(mac_string + 1), *(mac_string + 2), *(mac_string + 3), *(mac_string + 4), *(mac_string + 5));

    Info[4] = g_strdup_printf("%02x:%02x:%02x:%02x:%02x:%02x",  *mac_string, *(mac_string + 1), *(mac_string + 2), *(mac_string + 3), *(mac_string + 4), *(mac_string + 5));
    /* 同样，对其地址进行转换 */
///////////////////////////////////////////////////////////////
    struct arp_header *arp_protocol;
    /* ARP协议变量 */
    u_short protocol_type;
    /* 协议类型 */
    u_short hardware_type;
    /* 硬件类型 */
    u_short operation_code;
    /* 操作类型 */
    u_char *mac_string;
    /* 以太网地址 */
    struct in_addr source_ip_address;
    /* 源IP地址 */
    struct in_addr destination_ip_address;
    /* 目的IP地址 */
    u_char hardware_length;
    /* 硬件地址长度 */
    u_char protocol_length;
    /* 协议地址长度 */

    fprintf(stderr,"--------   ARP Protocol (Network Layer)    --------\n");
    arp_protocol = (struct arp_header*)(packet_content + 14);
    /*
     * 获得ARP协议数据。注意在这里要跳过以太网数据部分，它的长度刚好是14，所以在这里加上14，是指针跳过14个字节
     */
    hardware_type = ntohs(arp_protocol->arp_hardware_type);
    /* 获得硬件类型 */
    protocol_type = ntohs(arp_protocol->arp_protocol_type);
    /* 获得协议类型 */
    operation_code = ntohs(arp_protocol->arp_operation_code);
    /* 获得操作码 */
    hardware_length = arp_protocol->arp_hardware_length;
    /* 获得硬件地址长度 */
    protocol_length = arp_protocol->arp_protocol_length;
    /* 获得协议地址长度 */
    fprintf(stderr,"ARP Hardware Type:%d\n", hardware_type);
    fprintf(stderr,"ARP Protocol Type:%d\n", protocol_type);
    fprintf(stderr,"ARP Hardware Length:%d\n", hardware_length);
    fprintf(stderr,"ARP Protocol Length:%d\n", protocol_length);
    fprintf(stderr,"ARP Operation:%d\n", operation_code);

    switch (operation_code) /* 根据操作码进行判断是ARP什么类型协议 */
    {
        case 1:
            fprintf(stderr,"ARP Request Protocol\n");
            Info[0] = g_strdup_printf("%d %s", packet_length, "ARP请求");
            break;
            /* 是ARP查询协议 */
        case 2:
            fprintf(stderr,"ARP Reply Protocol\n");
	Info[0] = g_strdup_printf("%d %s", packet_length, "ARP回应");
            break;
            /* 是ARP应答协议 */
        case 3:
            fprintf(stderr,"RARP Request Protocol\n");
	Info[0] = g_strdup_printf("%d %s", packet_length, "RARP请求");
            break;
            /* 是RARP查询协议 */
        case 4:
            fprintf(stderr,"RARP Reply Protocol\n");
            Info[0] = g_strdup_printf("%d %s", packet_length, "RARP回应");
            break;
            /* 是RARP应答协议 */
        default:
            break;
    }
    fprintf(stderr,"Ethernet Source Address is : \n");
    mac_string = arp_protocol->arp_source_ethernet_address;
    fprintf(stderr,"%02x:%02x:%02x:%02x:%02x:%02x\n", *mac_string, *(mac_string + 1), *(mac_string + 2), *(mac_string + 3), *(mac_string + 4), *(mac_string + 5));
    /* 获得源以太网地址 */
    memcpy((void*) &source_ip_address, (void*) &arp_protocol->arp_source_ip_address, sizeof(struct in_addr));
    fprintf(stderr,"Source IP Address:%s\n", inet_ntoa(source_ip_address));
    /* 获得源IP地址 */

    Info[1] = g_strdup_printf("%s", inet_ntoa(source_ip_address));
    //Info[1]=g_locale_to_utf8(inet_ntoa(source_ip_address), sizeof(inet_ntoa(source_ip_address)), NULL, NULL, NULL);
    fprintf(stderr,"Ethernet Destination Address is : \n");
    mac_string = arp_protocol->arp_destination_ethernet_address;
    fprintf(stderr,"%02x:%02x:%02x:%02x:%02x:%02x\n", *mac_string, *(mac_string + 1), *(mac_string + 2), *(mac_string + 3), *(mac_string + 4), *(mac_string + 5));
    /* 获得目的以太网地址 */
    memcpy((void*) &destination_ip_address, (void*) &arp_protocol->arp_destination_ip_address, sizeof(struct in_addr));
    fprintf(stderr,"Destination IP Address:%s\n", inet_ntoa(destination_ip_address));
    /* 获得目的IP地址 */
Info[3] = g_strdup_printf("%s", inet_ntoa(destination_ip_address));
///////////////////////////////////////////////////////////////

    fprintf(stderr,"--------------------*****-----------------------\n");

    gtk_clist_set_column_justification(GTK_CLIST(clist2),0,GTK_JUSTIFY_CENTER);
   // gtk_clist_set_column_justification(GTK_CLIST(clist2),2,GTK_JUSTIFY_CENTER);

    gtk_clist_freeze((GtkCList*)clist2);
    gtk_clist_insert((GtkCList *)clist2, 0, Info);
    gtk_clist_thaw((GtkCList*)clist2);
}

void IP_callback(void)
{
    IPInfo[0] = g_strdup_printf("%s", "lie1");
    IPInfo[1] = g_strdup_printf("%s", "lie2");
    IPInfo[2] = g_strdup_printf("%s", "lie3");
    IPInfo[3] = g_strdup_printf("%s", "lie4");
    IPInfo[4] = g_strdup_printf("%s", "lie5");
    IPInfo[5] = g_strdup_printf("%s", "lie6");

    struct ip_header
    {
    #ifdef WORDS_BIGENDIAN
        u_int8_t ip_version: 4,  /* IP协议版本 */
        ip_header_length: 4; /* IP协议首部长度 */
    #else
        u_int8_t ip_header_length: 4, ip_version: 4;
    #endif
    u_int8_t ip_tos;
    /* TOS服务质量 */
    u_int16_t ip_length;
    /* 总长度 */
    u_int16_t ip_id;
    /* 标识 */
    u_int16_t ip_off;
    /* 偏移 */
    u_int8_t ip_ttl;
    /* 生存时间 */
    u_int8_t ip_protocol;
    /* 协议类型 */
    u_int16_t ip_checksum;
    /* 校验和 */
    struct in_addr ip_souce_address;
    /* 源IP地址 */
    struct in_addr ip_destination_address;
    /* 目的IP地址 */
    };
   struct bpf_program bpf_filter;
//const u_char *packet_content;
   packet_content=pcap_next(pcap_handle,&protocol_header);
   packet_num++;

   struct ip_header *ip_protocol;
    /* IP协议变量 */
    u_int header_length;
    /* 长度 */
    u_int offset;
    /* 偏移 */
    u_char tos;
    /* 服务质量 */
    u_int16_t checksum;
    /* 校验和 */
    ip_protocol = (struct ip_header*)(packet_content + 14);
    /* 获得IP协议数据内容，去掉以太网头 */
    checksum = ntohs(ip_protocol->ip_checksum);
    /* 获得校验和 */
    header_length = ip_protocol->ip_header_length *4;
    packet_total_len = packet_total_len + header_length;
    /* 获得长度 */
    tos = ip_protocol->ip_tos;
    /* 获得TOS */
    offset = ntohs(ip_protocol->ip_off);
    /* 获得偏移量 */

      fprintf(stderr,"--------------------*****-----------------------\n");
      fprintf(stderr,"Capture a Packet from net_interface :\n");
      fprintf(stderr,"%s \n", net_interface);
      /* 输出网络接口 */
      fprintf(stderr,"Capture Time is:\n");
      fprintf(stderr, "%s", ctime((const time_t*) &protocol_header.ts.tv_sec));
      /* 输出此数据包的时间信息 */

      fprintf(stderr,"----------- IP Protocol  (Network Layer)  -----------\n");
      fprintf(stderr,"IP Version:%d\n", ip_protocol->ip_version);
      fprintf(stderr,"Header length:%d\n", header_length);
      fprintf(stderr,"TOS:%d\n", tos);
      fprintf(stderr,"Total length:%d\n", ntohs(ip_protocol->ip_length));
      packet_total_len = packet_total_len + (int)ntohs(ip_protocol->ip_length);
      /* 获得总长度 */

      IPInfo[5] = g_strdup_printf("%d", ntohs(ip_protocol->ip_length));
      fprintf(stderr,"Identification:%d\n", ntohs(ip_protocol->ip_id));
      /* 获得标识 */
      fprintf(stderr,"Offset:%d\n", (offset &0x1fff) *8);
      fprintf(stderr,"TTL:%d\n", ip_protocol->ip_ttl);
      /* 获得TTL */
      fprintf(stderr,"Protocol:%d\n", ip_protocol->ip_protocol);
      /* 获得协议类型 */
      switch (ip_protocol->ip_protocol) /* 判断协议类型的值 */
      {
        case 6:
            fprintf(stderr,"The Transport Layer Protocol is TCP\n");
            IPInfo[4] = g_strdup_printf("%s", "TCP");
	TCP_callback();
            break;
            /* 如果协议类型为6，表示上层协议为TCP协议 */
        case 17:
            fprintf(stderr,"The Transport Layer Protocol is UDP\n");
            IPInfo[4] = g_strdup_printf("%s", "UDP");
            UDP_callback();
            break;
            /* 如果协议类型为17，表示上层协议为UDP协议 */
        case 1:
           fprintf(stderr,"The Transport Layer Protocol is ICMP\n");
           IPInfo[4] = g_strdup_printf("%s", "ICMP");
           ICMP_callback();
            break;
            /* 如果协议类型为1，表示传上层协议为ICMP协议 */
        default:
            break;
      }
      fprintf(stderr,"Header checksum:%d\n", checksum);
      fprintf(stderr,"Source address:%s\n",
              inet_ntoa(ip_protocol->ip_souce_address));
      /* 获得源IP地址 */

      IPInfo[0] = g_strdup_printf("%s", inet_ntoa(ip_protocol->ip_souce_address));

      fprintf(stderr,"Destination address:%s\n",
              inet_ntoa(ip_protocol->ip_destination_address));

      IPInfo[2] = g_strdup_printf("%s",
                                  inet_ntoa(ip_protocol->ip_destination_address));


      gtk_clist_freeze((GtkCList*)clist1);
      gtk_clist_insert((GtkCList *)clist1, 0, IPInfo);
      gtk_clist_thaw((GtkCList*)clist1);
}


void TCP_callback(void)
{
    struct tcp_header
    {
	u_int16_t	tcp_source_port;
	/* 源端口 */
	u_int16_t	tcp_destination_port;
	/* 目的端口 */
	u_int32_t	tcp_acknowledgement;
	/* 序列号 */
	u_int32_t	tcp_ack;
	/* 确认号 */
     #ifdef WORDS_BIGENDIAN
	u_int8_t	tcp_offset : 4,
	/* 偏移 */
	tcp_reserved : 4;
	/* 保留 */
     #else
	u_int8_t	tcp_reserved : 4,
	/* 保留 */
	tcp_offset : 4;
	/* 偏移 */
     #endif
	u_int8_t	tcp_flags;
	/* 标志 */
	u_int16_t	tcp_windows;
	/* 窗口大小 */
	u_int16_t	tcp_checksum;
	/* 校验和 */
	u_int16_t	tcp_urgent_pointer;
	/* 紧急指针 */
    };


    struct tcp_header	*tcp_protocol;

	/* TCP协议变量 */
	u_char	flags;
	/* 标记 */
	int	header_length;
	/* 首部长度 */
	u_short	source_port;
	/* 源端口号 */
	u_short	destination_port;
	/* 目的端口号 */
	u_short	windows;
	/* 窗口大小 */
	u_short	urgent_pointer;
	/* 紧急指针 */
	u_int	sequence;
	/* 序列号 */
	u_int	acknowledgement;
	/* 确认号 */
	u_int16_t checksum;
	/* 校验和 */
	tcp_protocol = (struct tcp_header *) (packet_content + 14 + 20);
	/* 获得TCP协议数据内容，应该跳过以太网头和IP头部分 */
	source_port = ntohs(tcp_protocol->tcp_source_port);
	/* 获得源端口号 */
	destination_port = ntohs(tcp_protocol->tcp_destination_port);
	/* 获得目的端口号 */
	header_length = tcp_protocol->tcp_offset * 4;
	/* 获得首部长度 */
	sequence = ntohl(tcp_protocol->tcp_acknowledgement);
	/* 获得序列号 */
	acknowledgement = ntohl(tcp_protocol->tcp_ack);
	/* 获得确认号 */
	windows = ntohs(tcp_protocol->tcp_windows);
	/* 获得窗口大小 */
	urgent_pointer = ntohs(tcp_protocol->tcp_urgent_pointer);
	/* 获得紧急指针 */
	flags = tcp_protocol->tcp_flags;
        /* 获得标记 */
	checksum = ntohs(tcp_protocol->tcp_checksum);
	/* 获得校验和 */
	fprintf(stderr,"-------  TCP Protocol  (Transport Layer)  -------\n");
	fprintf(stderr,"Source Port:%d\n", source_port);
	/* 输出源端口号 */
        IPInfo[1] = g_strdup_printf("%d", source_port);
        fprintf(stderr, "Destination Port:%d\n", destination_port);
        IPInfo[3] = g_strdup_printf("%d", destination_port);
	/* 输出目的端口号 */
	switch(destination_port)	/* 判断上层协议类型 */
	{
	case 80:	fprintf(stderr,"HTTP protocol\n"); break;
	/* 端口是80，表示上层协议是HTTP协议 */
	case 21:	fprintf(stderr,"FTP protocol\n"); break;
	/* 端口是21，表示上层协议是FTP协议 */
	case 23:	fprintf(stderr,"TELNET protocol\n"); break;
	/* 端口是23，表示上层协议是TELNET协议 */
	case 25:	fprintf(stderr,"SMTP protocol\n"); break;
	/* 端口是25，表示上层协议是SMTP协议 */
	case 110:	fprintf(stderr,"POP3 protocol\n"); break;
	/* 端口是110，表示上层协议是POP3协议 */
	default:	break;
	}

	fprintf(stderr,"Sequence Number:%u\n", sequence);
	/* 输出序列号 */
	fprintf(stderr,"Acknowledgement Number:%u\n", acknowledgement);
	/* 输出确认号 */
	fprintf(stderr,"Header Length:%d\n", header_length);
	/* 输出首部长度 */
	/*fprintf(stderr,"Reserved:%d\n", tcp_protocol->tcp_reserved);
	fprintf(stderr,"Flags:");

	输出标记 
	if(flags & 0x08) printf("PSH ");
	if(flags & 0x10) printf("ACK ");
	if(flags & 0x02) printf("SYN ");
	if(flags & 0x20) printf("URG ");
	if(flags & 0x01) printf("FIN ");
	if(flags & 0x04) printf("RST ");
*/
	fprintf(stderr,"Window Size:%d\n", windows);
	/* 输出窗口大小 */
	fprintf(stderr,"Checksum:%d\n", checksum);
	/* 输出校验和 */
	fprintf(stderr,"Urgent pointer:%d\n", urgent_pointer);
	/* 输出紧急指针 */
}

void UDP_callback(void)
{
   struct udp_header
   {
        u_int16_t udp_source_port;
        /* 源端口号 */
        u_int16_t udp_destination_port;
        /* 目的端口号 */
        u_int16_t udp_length;
        /* 长度 */
        u_int16_t udp_checksum;
        /* 校验和 */
   };

    struct udp_header *udp_protocol;
    /* UDP协议数据变量 */
    u_short source_port;
    /* 源端口号 */
    u_short destination_port;
    /* 目的端口号 */
    u_short length;
    /* 长度 */
    udp_protocol = (struct udp_header*)(packet_content + 14+20);
    /* 获得UDP协议数据内容 */
    source_port = ntohs(udp_protocol->udp_source_port);
    /* 获得源端口号 */

    IPInfo[1] = g_strdup_printf("%d", source_port);

    destination_port = ntohs(udp_protocol->udp_destination_port);
    /* 获得目的端口号 */

    IPInfo[3] = g_strdup_printf("%d", destination_port);

    length = ntohs(udp_protocol->udp_length);
    /* 获得长度 */
    fprintf(stderr,"----------  UDP Protocol  (Transport  Layer)  ----------\n");
    fprintf(stderr,"Source port:%d\n", source_port);
    fprintf(stderr,"Destination port:%d\n", destination_port);
    switch (destination_port)
    /* 根据端口号判断应用层协议类型 */
    {
        case 138:
            fprintf(stderr,"NETBIOS Datagram Service\n");
            break;
            /* 端口号为138，表示上层协议为NETBIOS 数据报服务 */
        case 137:
            fprintf(stderr,"NETBIOS Name Service\n");
            break;
            /* 端口号为137，表示上层协议为NETBIOS 名字服务 */
        case 139:
           fprintf(stderr,"NETBIOS session service\n");
            break;
            /* 端口号为139，表示上层协议为NETBIOS 会话服务 */
        case 53:
            fprintf(stderr,"name-domain server \n");
            break;
            /* 端口号为53，表示上层协议为域名服务 */
        default:
            break; /* 其他没有分析 */
    }
    fprintf(stderr,"Length:%d\n", length);
    fprintf(stderr,"Checksum:%d\n", ntohs(udp_protocol->udp_checksum));
}

void ICMP_callback(void)
{
    struct icmp_header
    {
        u_int8_t icmp_type;
        /* ICMP类型 */
        u_int8_t icmp_code;
        /* ICMP代码 */
        u_int16_t icmp_checksum;
        /* 校验和 */
        u_int16_t icmp_id_lliiuuwweennttaaoo;
        /* 标识符 */
        u_int16_t icmp_sequence;
        /* 序列号 */
    };

    struct icmp_header *icmp_protocol;
    /* ICMP协议变量 */
    icmp_protocol = (struct icmp_header*)(packet_content + 14+20);
    /* 获取ICMP协议数据内容，跳过以太网和IP协议部分 */
    fprintf(stderr,"----------  ICMP Protocol  (Transport Layer)  ----------\n");
    fprintf(stderr,"ICMP Type:%d\n", icmp_protocol->icmp_type);
    /* 获得ICMP类型 */
    switch (icmp_protocol->icmp_type) /* 根据ICMP类型进行判断 */
    {
        case 8:
            /* 类型为8，表示是回显请求报文 */
            fprintf(stderr,"ICMP Echo Request Protocol \n");
            fprintf(stderr,"ICMP Code:%d\n", icmp_protocol->icmp_code);
            IPInfo[1] = g_strdup_printf("%s", "ICMP Request");
            IPInfo[3] = g_strdup_printf("%s", "ICMP NO");
            /* 获得ICMP代码 */
            fprintf(stderr,"Identifier:%d\n",
            icmp_protocol->icmp_id_lliiuuwweennttaaoo);
            /* 获得标识符 */
            fprintf(stderr,"Sequence Number:%d\n", icmp_protocol->icmp_sequence);
            /* 获得序列号 */
            break;
        case 0:
            /* 类型为0，表示是回显应答报文 */
            fprintf(stderr,"ICMP Echo Reply Protocol \n");
            IPInfo[1] = g_strdup_printf("%s", "ICMP Relay");
            IPInfo[3] = g_strdup_printf("%s", "ICMP NO");
            fprintf(stderr,"ICMP Code:%d\n", icmp_protocol->icmp_code);
            /* 获得ICMP代码 */
            fprintf(stderr,"Identifier:%d\n",
                    icmp_protocol->icmp_id_lliiuuwweennttaaoo);
            /* 获得标识符 */
            fprintf(stderr,"Sequence Number:%d\n", icmp_protocol->icmp_sequence);
            /* 获得序列号 */
            break;
        default:
            break;
            /* 类型为其它值，在这里没有分析 */
    }
    fprintf(stderr,"ICMP Checksum:%d\n", ntohs(icmp_protocol->icmp_checksum));
    /* 获得校验和 */
}
void on_ARP_SAVE_pressed(GtkButton *button, gpointer user_data)
{
    fprintf(stderr, "ARP Save!\n");
}

void on_IP_SAVE_pressed(GtkButton *button, gpointer user_data)
{
    fprintf(stderr, "IP Save!\n");
}
